<template>
  <div>
    <input id="input" ref="input" style="display: none" type="file" @change="getSignedUploadUrl(currentUploadIndex)">
    <div class="subheading">{{title}}</div>
    <div class="d-flex align-center">
      <div v-if="show" v-for="(item, index) in fileList" v-bind:key="index" class="d-inline-block" @mouseenter="item.toolVisible=true" @mouseleave="item.toolVisible=false">
        <slot :url="item.src" :tool="item.toolVisible" :refs="refs" :index="index" :progressVisible="item.progressVisible" :progress="item.progress"></slot>
      </div>
      <div class="d-inline-block" v-if="fileList.length < max || max === -1">
        <slot name=add :length="fileList.length" :refs="refs"></slot>
      </div>
    </div>
  </div>
</template>

<script>
import SparkMD5 from 'spark-md5'
import { getPostObjectSignedUrl, PostObject, getObject } from '../api/oss'
export default {
  name: 'Uploader',
  props: {
    image: {},
    title: {},
    refs: {},
    base: {},
    max: {},
    pic: {},
    video: {},
    show: {
      type: [Boolean],
      default: true
    }
  },
  data: () => ({
    fileList: [ /* {
      src: 'https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top_86d58ae1.png?1',
      toolVisible: false,
      progressVisible: false,
      progress: 0
    }, {
      src: 'https://cn.vuejs.org/images/logo.png',
      toolVisible: false,
      progressVisible: false,
      progress: 0
    } */],
    currentUploadIndex: 0
  }),
  methods: {
    left (index) {
      if (index !== 0) {
        let temp = this.fileList[index]
        this.fileList[index] = this.fileList[index - 1]
        this.fileList[index - 1] = temp
      }
      this.fileList[index].toolVisible = false
      this.$nextTick(function () {
        this.fileList[index].toolVisible = true
      })
    },
    right (index) {
      if (index !== this.fileList.length - 1) {
        let temp = this.fileList[index]
        this.fileList[index] = this.fileList[index + 1]
        this.fileList[index + 1] = temp
      }
      this.fileList[index].toolVisible = false
      this.$nextTick(function () {
        this.fileList[index].toolVisible = true
      })
    },
    upload (index) {
      this.currentUploadIndex = index
      this.$refs.input.click()
    },
    delete (index) {
      this.fileList.splice(index, 1)
      this.clearFileInput()
    },
    getMd5 (file, index) {
      let fileObject = this.fileList[index]
      return new Promise(function (resolve, reject) {
        let fileReader = new FileReader()
        let blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice; let chunkSize = 2097152
        let chunks = Math.ceil(file.size / chunkSize); let currentChunk = 0; let spark = new SparkMD5()
        fileReader.onload = function (e) {
          fileObject.progress = ((currentChunk / chunks) * 100).toFixed(0)
          spark.appendBinary(e.target.result)
          currentChunk++
          if (currentChunk < chunks) {
            loadNext()
          } else {
            fileObject.progress = 100
            let md5 = spark.end()
            resolve(md5)
          }
        }
        function loadNext () {
          let start = currentChunk * chunkSize; let end = start + chunkSize >= file.size ? file.size : start + chunkSize
          fileReader.readAsBinaryString(blobSlice.call(file, start, end))
        }
        loadNext()
      })
    },
    uploadOss (file, index, policy, key, type) {
      PostObject(file, policy, key, this.fileList[index]).then((res) => {
        this.fileList[index].progressVisible = false
        if (type === 'video') {
          getObject(key).then((res) => {
            this.fileList[index].src = res.data.signedUrl
          })
        } else {
          this.$nextTick(function () {
            this.fileList[index].src = policy.host + key
            this.$emit('upload', policy.host + key)
          })
        }
        this.clearFileInput()
      })
    },
    clearFileInput () {
      this.$refs.input.value = ''
    },
    getSignedUploadUrl (index) {
      if (this.$refs.input.files.length === 0) {
        return
      }
      while (this.fileList.length <= index) {
        this.fileList.push({
          src: '',
          toolVisible: false,
          progressVisible: false,
          progress: 0
        })
      }
      this.fileList[index].progress = 0
      this.fileList[index].progressVisible = true
      let file = this.$refs.input.files[0]
      this.getMd5(file, index).then((md5) => {
        this.fileList[index].progressVisible = false
        let objectName = this.base + md5
        let type
        if (this.pic === true) {
          type = 'pic'
        } else if (this.video === true) {
          type = 'video'
        }
        getPostObjectSignedUrl(objectName, type).then((res) => {
          this.uploadOss(file, index, res.data.policy, objectName, type)
        })
      })
    }
  }
}
</script>

<style scoped>
</style>
